<?php
declare(strict_types=1);

namespace longhu;

use Fastknife\Service\BlockPuzzleCaptchaService;
use Fastknife\Service\ClickWordCaptchaService;
use longhuadmin\fiels\emuns\Driver;
use longhuadmin\system\data\logic\SystemConfigLogic;
use longhu\lang\server\LangCodeServices;
use longhu\lang\server\LangCountryServices;
use longhu\lang\server\LangTypeServices;
use think\exception\ValidateException;
use think\facade\Cache;
use think\facade\Config;
use think\facade\Db;
use think\helper\Str;

class Utils
{
  /**
   * 字符串转换成数组
   *
   * @time 2019年12月25日
   * @param string $string
   * @param string $dep
   * @return array
   */
    public static function stringToArrayBy(string  $string, $dep = ','): array
    {
        if (Str::contains($string, $dep)) {
            return explode($dep, trim($string, $dep));
        }

        return [$string];
    }

  /**
   * 搜索参数
   *
   * @time 2020年01月13日
   * @param array $params
   * @param array $range
   * @return array
   */
    public static function filterSearchParams(array $params, array $range = []): array
    {
        $search = [];

        if (!empty($range)) {
          foreach ($range as $field => $rangeField) {
            if (count($rangeField) === 1) {
              $search[$field] = [$params[$rangeField[0]]];
              unset($params[$rangeField[0]]);
            } else {
              $search[$field] = [$params[$rangeField[0]], $params[$rangeField[1]]];
              unset($params[$rangeField[0]], $params[$rangeField[1]]);
            }
          }
        }

        return array_merge($search, $params);
    }

    /**
     * 导入树形数据
     *
     * @time 2020年04月29日
     * @param $data
     * @param $table
     * @param string $pid
     * @param string $primaryKey
     * @return void
     */
    public static function importTreeData($data, $table, string $pid = 'parent_id', string $primaryKey = 'id')
    {
        foreach ($data as $value) {
            if (isset($value[$primaryKey])) {
                unset($value[$primaryKey]);
            }

            $children = $value['children'] ?? false;
            if($children) {
                unset($value['children']);
            }

            // 首先查询是否存在
            $menu = Db::name($table)
                        ->where('permission_name', $value['permission_name'])
                        ->where('module', $value['module'])
                        ->where('permission_mark', $value['permission_mark'])
                        ->find();

            if (!empty($menu)) {
                $id = $menu['id'];
            } else {
                $id = Db::name($table)->insertGetId($value);
            }
            if ($children) {
                foreach ($children as &$v) {
                    $v[$pid] = $id;
                    $v['level'] = !$value[$pid] ? $id : $value['level'] . '-' .$id;
                }
                self::importTreeData($children, $table, $pid);
            }
        }
    }

    /**
     *  解析 Rule 规则
     *
     * @time 2020年05月06日
     * @param $rule
     * @return array
     */
    public static function parseRule($rule): array
    {
        [$controller, $action] = explode(Str::contains($rule, '@') ? '@' : '/', $rule);

        $controller = explode('\\', $controller);

        $controllerName = lcfirst(array_pop($controller));

        array_pop($controller);

        $module = array_pop($controller);

        return [$module, $controllerName, $action];
    }


    /**
     * get controller & action
     *
     * @time 2020年10月12日
     * @param $rule
     * @return false|string[]
     * @throws \ReflectionException
     */
    public static function isMethodNeedAuth($rule)
    {
        list($controller, $action) = explode(Str::contains($rule, '@') ? '@' : '/', $rule);

        $docComment = (new \ReflectionClass($controller))->getMethod($action)->getDocComment();

        if (! $docComment) {
            return false;
        }

        return strpos($docComment, config('catch.permissions.method_auth_mark')) !== false;
    }


    /**
     * 表前缀
     *
     * @time 2020年05月22日
     * @return mixed
     */
    public static function tablePrefix()
    {
        return \config('database.connections.mysql.prefix');
    }

    /**
     * 删除表前缀
     *
     * @time 2020年12月01日
     * @param string $table
     * @return string|string[]
     */
    public static function tableWithoutPrefix(string $table)
    {
        return str_replace(self::tablePrefix(), '', $table);
    }

    /**
     * 添加表前缀
     *
     * @time 2020年12月26日
     * @param string $table
     * @return string
     */
    public static function tableWithPrefix(string $table): string
    {
        return Str::contains($table, self::tablePrefix()) ?
                    $table : self::tablePrefix() . $table;
    }

    /**
     * 是否是超级管理员
     *
     * @time 2020年07月04日
     * @return bool
     */
    public static function isSuperAdmin(): bool
    {
        return request()->user()->id == config('catch.permissions.super_admin_id');
    }

//    /**
//     * 获取配置
//     *
//     * @time 2020年09月07日
//     * @param $key
//     * @return mixed
//     */
//    public static function config($key)
//    {
//        return Config::where('key', $key)->value('value');
//    }

    /**
     * public path
     *
     * @param string $path
     * @time 2020年09月08日
     * @return string
     */
    public static function publicPath(string $path = ''): string
    {
        return root_path($path ? 'public/'. $path : 'public');
    }


    /**
     * 过滤空字符字段
     *
     * @time 2021年01月16日
     * @param $data
     * @return mixed
     */
    public static function filterEmptyValue($data)
    {
        foreach ($data as $k => $v) {
            if (!$v) {
                unset($data[$k]);
            }
        }

        return $data;
    }

//    /**
//     * 设置 filesystem config
//     *
//     * @time 2021年03月01日
//     * @return void
//     */
//    public static function setFilesystemConfig()
//    {
//        $configModel = app(Config::class);
//
//        $upload = $configModel->where('key', 'upload')->find();
//
//        if ($upload) {
//            $disk = app()->config->get('filesystem.disks');
//
//            $uploadConfigs = $configModel->getConfig($upload->component);
//
//            if (!empty($uploadConfigs)) {
//                // 读取上传可配置数据
//                foreach ($uploadConfigs as $key => &$config) {
//                    // $disk[$key]['type'] = $key;
//                    // 腾讯云配置处理
//                    if (strtolower($key) == 'qcloud') {
//                        $config['credentials'] = [
//                            'appId' => $config['app_id'] ?? '',
//                            'secretKey' => $config['secret_key'] ?? '',
//                            'secretId' => $config['secret_id'] ?? '',
//                        ];
//                        $readFromCdn = $config['read_from_cdn'] ?? 0;
//                        $config['read_from_cdn'] = intval($readFromCdn) == 1;
//                    }
//                    // OSS 配置
//                    if (strtolower($key) == 'oss') {
//                        $isCname = $config['is_cname'] ?? 0;
//                        $config['is_cname'] = intval($isCname) == 1;
//                    }
//                }
//
//                // 合并数组
//                array_walk($disk, function (&$item, $key) use ($uploadConfigs) {
//                    if (!in_array($key, ['public', 'local'])) {
//                        if ($uploadConfigs[$key] ?? false) {
//                            foreach ($uploadConfigs[$key] as $k => $value) {
//                                $item[$k] = $value;
//                            }
//                        }
//                    }
//                });
//
//
//                $default = Utils::config('site.upload');
//                // 重新分配配置
//                app()->config->set([
//                    'default' =>  $default ? : 'local',
//                    'disks' => $disk,
//                ], 'filesystem');
//            }
//        }
//    }

    /**
     * 缓存操作
     *
     * @time 2021年06月18日
     * @param string $key
     * @param \Closure $callable
     * @param int $ttl
     * @param string $store
     * @return mixed
     *@throws \Psr\SimpleCache\InvalidArgumentException
     */
    public static function cache(string $key, \Closure $callable, int $ttl = 0, string $store = 'redis')
    {
        if (Cache::store($store)->has($key)) {
            return Cache::store($store)->get($store);
        }

        $cache = $callable();

        Cache::store($store)->set($key, $cache, $ttl);

        return $cache;
    }


    /**
     * 创建目录
     *
     * @time 2019年12月16日
     * @param string $directory
     * @return string
     */
    public static function makeDirectory(string $directory): string
    {
        if (!is_dir($directory) && !mkdir($directory, 0777, true) && !is_dir($directory)) {
            throw new \RuntimeException(sprintf('Directory "%s" was not created', $directory));
        }

        return $directory;
    }


    /**
     * 获取模型路径
     * @param $model
     * @param $module
     * @return string
     */
    public static function getModelFilePath($model, $module)
    {
        return app_path() . $module . DIRECTORY_SEPARATOR . 'model' . DIRECTORY_SEPARATOR . $model . '.php';
    }

    /**
     *
     * @time 2019年11月30日
     * @return string
     */
    public static function directory(): string
    {
        return app()->getRootPath() . 'app' . DIRECTORY_SEPARATOR;
    }

    public static function endecodeUserId($string, $action = 'encode') {
        $startLen = 13;
        $endLen = 8;
        $coderes = '';
        #TOD 暂设定uid字符长度最大到9
        if ($action=='encode') {
            $uidlen = strlen($string);
            $salt = 'yourself_code';
            $codestr = $string.$salt;
            $encodestr = hash('md4', $codestr);
            $coderes = $uidlen.substr($encodestr, 5,$startLen-$uidlen).$string.substr($encodestr, -12,$endLen);
            $coderes = strtoupper($coderes);
        }elseif($action=='decode'){
            $strlen = strlen($string);
            $uidlen = $string[0];
            $coderes = substr($string, $startLen-$uidlen+1,$uidlen);
        }
        return  $coderes;
    }
    public static function msecdate($time)
    {
        $tag='Ymd H:i:s';
        $a = substr((string)$time,0,10);
        $b = substr((string)$time,10);
        $date = date($tag,intval($a));
        return $date;
    }

    /**
     * 生成毫秒时间戳
     * @return float
     */
    public static function msectime()
    {
        list($msec, $sec) = explode(' ', microtime());
        $msectime =  (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
        return $msectime;
    }

//    /**
//     * @param string $captchaType
//     * @param string $captchaVerification
//     * @return true
//     */
//    public static function ajCaptchaCheckTwo(string $captchaType, string $captchaVerification)
//    {
//        self::ajGetSerevice($captchaType)->verificationByEncryptCode($captchaVerification);
//        return true;
//    }

//    /**
//     * @param string $captchaType
//     * @return BlockPuzzleCaptchaService|ClickWordCaptchaService
//     */
//    public static function ajGetSerevice(string $captchaType)
//    {
//        $config = Config::get('admin.ajcaptcha');
//        switch ($captchaType) {
//            case "clickWord":
//                $service = new ClickWordCaptchaService($config);
//                break;
//            case "blockPuzzle":
//                $service = new BlockPuzzleCaptchaService($config);
//                break;
//            default:
//                throw new ValidateException('captchaType参数不正确！');
//        }
//        return $service;
//    }


    public static function sortListTier($data, $pid = 0, $field = 'pid', $pk = 'id', $html = '|-----', $level = 1, $clear = true)
    {
        static $list = [];
        if ($clear) $list = [];
        foreach ($data as $k => $res) {
            if ($res[$field] == $pid) {
                $res['html'] = str_repeat($html, $level);
                $list[] = $res;
                unset($data[$k]);
                self::sortListTier($data, $res[$pk], $field, $pk, $html, $level + 1, false);
            }
        }
        return $list;
    }

//    /**
//     * @return void
//     */
//    public static function setFilesystemConfig():void
//    {
//        //获取上传文件储存方式
//        $storageType = 'local';
//        $config = app(SystemConfigLogic::class);
//        $configLists = $config->getConfigs(0,'system_storage_set');
//        $configData = [];
//        if(!empty($configLists)){
//            foreach ($configLists as $key=>$value){
//                if($value['key_field'] === 'storage_type'){
//                    if(!empty($value['field_value'])){
//                        $storageType = $value['field_value'];
//                    }
//                }else{
//                    $configData[$value['key_field']] = $value['field_value'];
//                }
//            }
//        }
//        $disks = config('filesystem.disks');
//       if($storageType === Driver::QIQNIU->value()){
//           $configs = [
//               'type'=>$storageType,
//               'accessKey' => empty($configData['qiniu_access_key'])?'':$configData['qiniu_access_key'],
//               'secretKey' =>  empty($configData['qiniu_secret_key'])?'':$configData['qiniu_secret_key'],
//               'bucket'    =>  empty($configData['qiniu_bucket'])?'':$configData['qiniu_bucket'],
//               'domain'    => empty($configData['qiniu_domain'])?'':$configData['qiniu_domain'],
//           ];
//           $disks[$storageType] = $configs;
//       }elseif ($storageType === Driver::OSS->value()) {
//           $configs = [
//               'type'=>$storageType,
//               'accessKey' => empty($configData['oss_access_key'])?'':$configData['oss_access_key'],
//               'secretKey' =>  empty($configData['oss_secret_key'])?'':$configData['oss_secret_key'],
//               'name'    =>  empty($configData['oss_bucket'])?'':$configData['oss_bucket'],
//               'region'    =>  empty($configData['oss_region'])?'':$configData['oss_region'],
//               'domain'    =>  empty($configData['oss_domain'])?'':$configData['oss_domain'],
//               'acl'    =>  empty($configData['oss_acl'])?'':$configData['oss_acl'],
//               'cdn'    => empty($configData['oss_cdn'])?'':$configData['oss_cdn'],
//               'cname'    => empty($configData['oss_cname'])?'':$configData['oss_cname'],
//           ];
//           $disks[$storageType] = $configs;
//       }else {  //本地
//           $configs = [
//               'type'=>$storageType,
//               'root' => app()->getRuntimePath() . 'storage',
//               'url' => '/storage'
//           ];
//           $disks[$storageType] = $configs;
//       }
//       Config::set([
//           'default' => $storageType,
//           'disks' =>$disks
//       ],'filesystem');
//    }

    public static function make_path($path, int $type = 2, bool $force = false)
    {
        $path = '/' . ltrim(rtrim($path));
        switch ($type) {
            case 1:
                $path .= '/' . date('Y');
                break;
            case 2:
                $path .= '/' . date('Y') . '/' . date('m');
                break;
            case 3:
                $path .= '/' . date('Y') . '/' . date('m') . '/' . date('d');
                break;
        }
        try {
            if (is_dir(app()->getRootPath() . 'public' . '/' . 'uploads' . $path) == true || mkdir(app()->getRootPath() . 'public' . '/' . 'uploads' . $path, 0777, true) == true) {
                return trim(str_replace('/', '/', $path), '.');
            } else return '';
        } catch (\Exception $e) {
            if ($force)
                throw new \Exception($e->getMessage());
            return '';
        }
    }


    /**
     * 生产不重复的随机字符串
     */
    public function createNonceStr($length = 32)
    {
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return date('Ymd') . $str;
    }

}
